// Copyright 2022 jeff.li. and/or its affiliates.

#pragma once

#include <condition_variable>
#include <future>
#include <memory>
#include <mutex>
#include <queue>
#include <string>
#include <thread>
#include <vector>

#ifdef _WIN32
#include <windows.h>
typedef DWORD pid_t;
#else

#include <unistd.h>

#endif

#include <tbir/runtime/threadpool/i_thread_pool.h>

namespace tbir::runtime::internal {

    class LockBasedRunnable : public IRunnable {
    public:
        bool Done() override {
            return finish_;
        }

    protected:
        void SetDone() override {
            std::lock_guard<std::mutex> lock(mutex_);
            finish_ = true;
        }

    private:
        std::mutex mutex_;
        bool finish_ = false;
    };

    class LockBasedThreadPool : public IThreadPool {
    public:
        typedef std::unique_lock<std::mutex> Lock;

        LockBasedThreadPool(size_t thread_num, const std::string &name);

        ~LockBasedThreadPool() override;

        void Enqueue(IRunnablePtr &runner, size_t seq) override;

        void EnqueueBulk(std::vector<IRunnablePtr> &runners) override;

        size_t GetThreadsNum() const override;

        std::vector<std::thread::id> GetThreadIds() const override;

    private:
        static void ThreadEntry(LockBasedThreadPool *pool, const std::string &name);

    private:
        std::vector<std::thread> workers_;
        std::queue<IRunnablePtr> tasks_;

        bool stop_ = false;

        std::mutex mutex_;
        std::condition_variable cond_;
        pid_t belong_to_pid_;
    };

}  // namespace tbir::runtime::internal
